#ifndef DW_SYSTEM_LOGGER_H
#   define DW_SYSTEM_LOGGER_H

#include "base/singleton.h" 

#include <string>
#include <vector>

namespace dw {
	namespace system {

class Logger
:	public dw::base::Singleton< Logger >
{
public : //! @name Types definitions
	//! @{
	class Listener;

	enum Level
	{
		LVL_DEBUG,
		LVL_INFO,
		LVL_WARNING,
		LVL_ERROR,
		LVL_COUNT,
		LVL_ALL = (0x01 << LVL_DEBUG) | (0x01 << LVL_INFO) | (0x01 << LVL_WARNING) | (0x01 << LVL_ERROR)
	};
	//! @}

public : //! @name Helpers
	//! @{
	const std::string& levelToString(Level level);
	//! @}

public : //! @name Commands
	//! @{
	void log(Logger::Level level, const char* format, ...);

	void debug(const char* format, ...);
	void inform(const char* format, ...);
	void warn(const char* format, ...);
	void error(const char* format, ...);

	void registerListener(Listener* listener);
	void unregisterListener(Listener* listener);
	//! @}

public : //! @name Setup
	//! @{
	void enable(Level level);
	void disable(Level level);
	//! @}

public : //! @name State
	//! @{
	bool levelIsEnabled(Level level) const ;
	//! @}

private : //! @name Helpers
	//! @{
	void _logInternal(Level level, const std::string& message);
	//! @}

protected : //! @name Construction & destruction
	//! @{
	Logger();
	~Logger();
	//! @}

private : //! @name Data
	//! @{
	static const std::string _levelNames[LVL_COUNT];

	typedef std::vector< Listener* > ListenerCollection;
	ListenerCollection _listeners;
	int _filter;
	//! @}

private : //! @name Friends
	//! @{
	friend class dw::base::Singleton< Logger >;
	//! @}
};

#define dwLogDebug dw::system::Logger::getInstance().debug
#define dwLogInform dw::system::Logger::getInstance().inform
#define dwLogWarn dw::system::Logger::getInstance().warn
#define dwLogError dw::system::Logger::getInstance().error

	} // namespace system
} // namespace dw

#	include "system/logger.inl"

#endif // !DW_SYSTEM_LOGGER_H
